<script setup lang="ts">
import { getTrees, GetNames } from '@/api/base/treeDicItem'

import { propTypes } from '@/utils/propTypes'
import { ref, unref, watch } from 'vue'
import { treeEvent } from '../types'
import { treeDicItemModel } from '@/api/types/dictType'
import { joinStr } from '@/utils'

const emit = defineEmits(['load', 'change', 'update:modelValue'])
const chioseKey = ref<string[] | string | null>(null)
const trees = ref<treeDicItemModel[]>([])
const names = ref<string[]>([])
const checkstrictly = ref<Boolean>(false)
const itemCache = {}
const props = defineProps({
  dicId: propTypes.string,
  parentId: propTypes.string,
  renderAfterExpand: propTypes.bool.def(false),
  multiple: propTypes.bool.def(false),
  placeholder: propTypes.string.def('请选择'),
  isAutoChiose: propTypes.bool.def(false),
  isChioseEnd: propTypes.bool.def(true),
  modelValue: propTypes.any,
  readonly: propTypes.bool.def(false),
  source: propTypes.object,
  labelField: propTypes.string,
  clearable: propTypes.bool
})
const defProps = {
  key: 'DicValue',
  label: 'DicText',
  children: 'Children'
}
const reset = () => {
  if (props.readonly) {
    if (props.modelValue == null) {
      names.value = []
      return
    } else if (props.multiple && props.modelValue.length !== 0) {
      loadNames(props.modelValue)
    } else if (props.multiple === false) {
      loadNames([props.modelValue])
    } else {
      names.value = []
    }
    refreshLabel()
  } else {
    loadTree()
  }
}
const loadTree = async () => {
  const res = await getTrees(props.dicId, props.parentId)
  checkstrictly.value = props.isChioseEnd == false
  res.forEach((c) => {
    itemCache[c.DicValue] = c
    format(c)
  })
  trees.value = res
  refreshLabel()
  emit('load', {
    source: res,
    items: itemCache
  })
}
const format = (row) => {
  if (row.Children) {
    if (row.Children.length === 0) {
      row.Children = null
    } else {
      row.Children.forEach((c) => {
        itemCache[c.DicValue] = c
        format(c)
      })
    }
  }
}
const refreshLabel = () => {
  if (props.source == null || props.labelField == null) {
    return
  } else if (props.readonly) {
    unref(props.source)[props.labelField] = unref(names)?.join(',')
  } else if (chioseKey.value == null || chioseKey.value.length === 0) {
    unref(props.source)[props.labelField] = null
  } else if (Array.isArray(chioseKey.value)) {
    const list = chioseKey.value
    unref(props.source)[props.labelField] = joinStr(list, (c: string) => itemCache[c].DicText)
  } else {
    unref(props.source)[props.labelField] = itemCache[chioseKey.value as string].DicText
  }
}
const chioseNode = () => {
  const e: treeEvent = {
    isMultiple: props.multiple,
    item: itemCache,
    value: chioseKey.value
  }
  refreshLabel()
  emit('update:modelValue', chioseKey.value)
  emit('change', chioseKey.value, e)
}
const loadNames = async (ids) => {
  const list = await GetNames(props.dicId, ids)
  names.value = list
}
const resetValue = (val) => {
  if (val == null) {
    chioseKey.value = props.multiple ? [] : null
  } else if (props.multiple) {
    chioseKey.value = Array.isArray(val) ? val : [val]
  } else if (Array.isArray(val)) {
    chioseKey.value = val.length > 0 ? val[0] : null
  } else {
    chioseKey.value = val
  }
}
watch(
  () => props.dicId,
  (dic: string) => {
    if (dic) {
      reset()
    }
  },
  {
    immediate: true
  }
)
watch(
  () => props.multiple,
  (val) => {
    if (
      val &&
      props.modelValue != null &&
      Array.isArray(props.modelValue) &&
      props.modelValue.length > 1
    ) {
      resetValue(null)
    } else {
      resetValue(props.modelValue)
    }
  },
  {
    immediate: false
  }
)
watch(
  () => props.modelValue,
  (val) => {
    resetValue(val)
    refreshLabel()
  },
  {
    immediate: true
  }
)
</script>
<template>
  <el-space v-if="readonly" class="itemNames">
    <span v-for="i in names" :key="i">{{ i }}</span>
  </el-space>
  <el-tree-select
    v-else
    v-model="chioseKey"
    :data="trees"
    :default-expand-all="true"
    :highlight-current="true"
    :expand-on-click-node="false"
    :placeholder="placeholder"
    :props="defProps"
    :check-strictly="checkstrictly"
    :render-after-expand="props.renderAfterExpand"
    :show-checkbox="props.multiple"
    nodeKey="DicValue"
    :multiple="props.multiple"
    check-on-click-node
    :style="$attrs.style"
    :class="$attrs.class"
    :clearable="props.clearable"
    @change="chioseNode"
  />
</template>

<style scoped>
.itemNames {
  display: inline-block;
  line-height: 20px;
  min-width: 100px;
}
.itemNames span {
  padding: 5px;
}
</style>
